<?php
/**
 * @class DAO
 * @extend PDO
 * @file dao.class.php
 * @author david djian
 * @copyright 2008
 * @version 1.0
 */
abstract class DAO extends PDO {

  protected $transactionActive = false;

  /**
   * DAO::__construct()
   *
   * @param mixed $dbtype
   * @param mixed $hostname
   * @param mixed $username
   * @param mixed $password
   * @param mixed $dbname
   * @return
   */
  public function __construct($dsn, $username, $password) {

    parent::__construct($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

    //rapport d'erreur, lance des exception
    $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    //Définit la classe de la requête fournie par l'utilisateur d�riv�e de PDOStatement. Ne peut �tre utilis� avec des instances persistantes de PDO.
    $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DAOStatement', array($this)));
    //$this->setAttribute(PDO::MYSQL_ATTR_LOCAL_INFILE);
  }


  /**
   * DAO::query()
   * Redéfinition de la fonction PDO::query() pour prise en charge du debug
   *
   * @param mixed $params mêmes paramètres que ceux de la fonction query de PDO
   *
   * @return
   */
  public function query() {
    $args = func_get_args();
    $result = null;
    $explain_info = '';
    $error = null;

    if(ecEnvironment::isDebug())
    {
      if (_bl_create_times)
      {
        bl_time('Start Query '.substr($args[0], 0, 30)).'...';
      }
      $debug = debug_backtrace();

      $t_start = bl_get_time();
    }
    try{
        if(count($args) == 1) {
          $result = parent::query($args[0]);
        }
        elseif(count($args) == 3) {
          $result = parent::query($args[0], $args[1], $args[2]);
        }
        elseif(count($args) == 4) {
          $result = parent::query($args[0], $args[1], $args[2], $args[3]);
        }
    }
    catch (PDOException $e) {
        $error = "Failed Request: " . $e->getMessage() . "\n";
    }

    if(ecEnvironment::isDebug())
    {
        $t_stop = bl_get_time($t_start);

    	$q = trim(strtolower($args[0]));
    	$insert_id = $results = '0';

        // if is insert get the last id
    	if (substr($q, 0, 6) == 'insert')
        {
    	  $insert_id = parent::lastInsertId();
    	}
        else
    		if (substr($q, 0, 6) == 'select') { // if is select get num rows

    			if (_bl_explain_sql && $error == null) {
    				$sql_explain = parent::query("EXPLAIN " . $args[0]);
    				$explain = $sql_explain->fetchAssoc();

    				$explain_info = '
    				<p class="bl_explain">
    					<strong>EXPLAIN</strong> -&gt;Table: <em>' . $explain['table'] .
    					'</em> <span class="bl_msg_separator">|</span>
    					Type: <em>' . $explain['type'] .
    					'</em> <span class="bl_msg_separator">|</span>
    					Possible Keys: <em>' . $explain['possible_keys'] .
    					'</em> <span class="bl_msg_separator">|</span>
    					Key: <em>' . $explain['key'] .
    					'</em> <span class="bl_msg_separator">|</span>
    					Key len: <em>' . $explain['key_len'] .
    					'</em> <span class="bl_msg_separator">|</span>
    					Ref: <em>' . $explain['ref'] .
    					'</em> <span class="bl_msg_separator">|</span>
    					Extra: <em>' . $explain['Extra'] . '</em>
    				</p>';

    				$results = $explain['rows'];
    			} elseif($error == null) {
    				$results = $result->rowCount();
    			}

    		}

    	// add to the querys array
    	_bl::$count_querys++;
    	$c = _bl::$count_querys; // :)
    	_bl::$msg_sql[$c]['query'] = $args[0];
    	_bl::$msg_sql[$c]['time'] = $t_stop;
    	_bl::$msg_sql[$c]['insert'] = $insert_id;
    	_bl::$msg_sql[$c]['result'] = $results;
    	_bl::$msg_sql[$c]['explain'] = $explain_info;
    	_bl::$msg_sql[$c]['error'] = ($error != null) ? '<span class="error">' . $error . '</span>' : '';
    	_bl::$msg_sql[$c]['file'] = $debug[0]['file'];
    	_bl::$msg_sql[$c]['line'] = $debug[0]['line'];
    }

    return $result;

  }

  /**
   * DAO::debutTransaction()
   * verification si la transaction est active ou pas en fonction de $transactionActive
   *
   * @return
   */
  public function debutTransaction() {
    if($this->transactionActive) {
      return false;
    }
    else {
      $this->transactionActive = parent::beginTransaction();
      return $this->transactionActive;
    }
  }

  /**
   * DAO::valideTransaction()
   * Post et renvoie un �tat inactif de la transaction
   *
   * @return
   */
  public function valideTransaction() {
    parent::commit();
    $this->transactionActive = false;
  }

  /**
   * DAO::annuleTransaction()
   * Annule la transaction et renvoie un �tat inactif de la transaction
   *
   * @return
   */
  public function annuleTransaction() {
    $this->rollBack();
    $this->transactionActive = false;
  }

  /**
   * DAO::select()
   *
   * @param mixed $tablename
   * @param mixed $champ
   * @param string $condition
   * @param string $tri
   * @return
   */
  public function select($tablename, $champ, $condition="", $tri="") {

    if($condition != "") {
      $query = "SELECT ".$champ." FROM ".$tablename." WHERE ".$condition." ".$tri;
    }
    else {
      $query = "SELECT ".$champ." FROM ".$tablename." ".$tri;
    }
    //echo $query."<br/>";
    return $this->query($query);
  }

  /**
   * DAO::insert()
   *
   * @param mixed $tablename
   * @param mixed $champ
   * @param mixed $value
   * @return
   */
  public function insert($tablename, $champ, $value) {
    $query = "INSERT INTO ".$tablename." (".$champ.") VALUES (".$value.")";
    return $this->query($query);
  }


  /**
   * DAO::update()
   *
   * @param mixed $tablename
   * @param mixed $update
   * @param string $condition
   * @return
   */
  public function update($tablename, $update ,$condition="") {
    $query = "UPDATE ".$tablename." SET ".$update." WHERE ".$condition;
    //echo $query.'<br>';
    return $this->query($query);
  }

  /**
   * DAO::delete()
   *
   * @param mixed $tablename
   * @param mixed $condition
   * @return
   */
  public function delete($tablename, $condition) {
    $query = "DELETE FROM ".$tablename." WHERE ".$condition;
    //echo $query.'<br>';
    return $this->query($query);
  }

}

?>